Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ML-KEM (FIPS 203). #470

Merged
merged 1 commit into from
Aug 16, 2024
Merged

Add ML-KEM (FIPS 203). #470

merged 1 commit into from
Aug 16, 2024

Conversation

bwesterb
Copy link
Member

@bwesterb bwesterb commented Jan 4, 2024

Implementation of ML-KEM (FIPS 203).

We keep Kyber around (for now) as it's currently widely deployed. Code differences between them are minimal anyway.

Changes from IPD:

  1. Add test against ACVP test vectorswhich still have to be updated to match FIPS203. are updated
  2. Add domain separation in internal PKE key generation.
  3. Add modulus check on public key.

@bwesterb bwesterb marked this pull request as draft January 4, 2024 21:45
@bwesterb bwesterb changed the title [WIP] Add ML-KEM (FIPS 203). [DNM] Add ML-KEM (FIPS 203). Feb 15, 2024
Copy link
Contributor

@Lekensteyn Lekensteyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of nits, the only really "wrong" thing is a documentation comment.

LGTM otherwise!

kem/kyber/templates/pkg.templ.go Outdated Show resolved Hide resolved
kem/kyber/templates/pkg.templ.go Outdated Show resolved Hide resolved
kem/kyber/templates/pkg.templ.go Outdated Show resolved Hide resolved
kem/kyber/templates/pkg.templ.go Outdated Show resolved Hide resolved
@@ -143,6 +151,9 @@ func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) {
// c = Kyber.CPAPKE.Enc(pk, m, r)
pk.pk.EncryptTo(ct, m[:], kr[32:])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While at it, maybe we can use a name for this constant. This matches the type of K in the Algorithm 16 from FIPS 203 ("derive shared secret K and randomness r") and is consistent with your other use of kr[:SharedKeySize] below.

Suggested change
pk.pk.EncryptTo(ct, m[:], kr[32:])
pk.pk.EncryptTo(ct, m[:], kr[SharedKeySize:])

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is accidental, and that 32 is not the shared key size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not following.

My understanding is that the first part of kr is the shared secret key. So kr[SharedKeySize:] would skip the shared secret key, and refer to the remaining part, r.

Output: shared key K ∈ B32
(K, r) ← G(m ∥ H(ek))           ▷ derive shared secret key K and randomness r
c ← K-PKE.Encrypt(ek, m, r)     ▷ encrypt m using K-PKE with randomness r

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Kyber the first 32 bytes does not contain the returned shared secret, but an intermediate key that happens to be 32 bytes as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, what about replacing kr[:SharedKeySize] by kr[:32] to avoid that implication?

kem/kyber/templates/pkg.templ.go Outdated Show resolved Hide resolved
@bwesterb
Copy link
Member Author

Lots of nits, the only really "wrong" thing is a documentation comment.

Thanks. Addressed.

@mvd-ows
Copy link

mvd-ows commented Jul 4, 2024

Any updates on this? Is there something that prevents it from being merged?

Our view is that the "draft" status will probably remain for some time to come. Hopefully we can see this merged before the draft label is removed.

@bwesterb
Copy link
Member Author

bwesterb commented Jul 4, 2024

Is there something that prevents it from being merged?

ML-KEM is not final and could well have a breaking change compared to the initial public draft which is implemented by this PR.

Our view is that the "draft" status will probably remain for some time to come.

We expect the final version of ML-KEM this year, and that could be as early as this month.

@mvd-ows
Copy link

mvd-ows commented Jul 4, 2024

Thank you for those clarifications, and the quick reply.

@@ -7,8 +7,10 @@ package main

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please move these files used to generate code to an internal folder.

/kem/internal/gen.go
/kem/internal/pkg.templ.go

Generated packages:

/kem/kyber*
/kem/mlkem*

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please move these files used to generate code to an internal folder.

Shall we do that in a separate PR? It's not only Kyber that has a gen.go outside of an internal.

@bwesterb bwesterb removed the on-hold label Aug 13, 2024
@bwesterb bwesterb self-assigned this Aug 13, 2024
@bwesterb bwesterb changed the title [DNM] Add ML-KEM (FIPS 203). Add ML-KEM (FIPS 203). Aug 13, 2024
@bwesterb bwesterb marked this pull request as ready for review August 13, 2024 10:48
@bwesterb bwesterb force-pushed the bas/ml-kem branch 3 times, most recently from 6d7c6f4 to 9095c87 Compare August 13, 2024 11:27
t.Fatal(err)
}

if dk.Equal(dk2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the error message, aren't these two conditions inverted?

Suggested change
if dk.Equal(dk2) {
if !dk.Equal(dk2) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. Well spotted. Let me figure out why it fails...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, apparently the ACVP test vectors haven't been updated yet.

// key is not normalized.
func (pk *PublicKey) UnpackMLKEM(buf []byte) error {
if len(buf) != PublicKeySize {
return kem.ErrPubKeySize
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous Pack/Unpack function panics instead of returning an error when the size does not match.

We keep Kyber around (for now) as it's currently widely deployed.
Code differences between them are minimal anyway.

Tests against NIST's ACVP test vectors.
@armfazh armfazh merged commit 2b4626d into main Aug 16, 2024
10 checks passed
@armfazh armfazh deleted the bas/ml-kem branch August 16, 2024 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants